// 图像处理算法类 - 保持原始精度
export class ImageAlgorithms {
    constructor() {
        this.canvas = document.createElement('canvas');
        // 关键性能优化：设置 willReadFrequently 为 true
        try {
            this.ctx = this.canvas.getContext('2d', {
                willReadFrequently: true
            });
        } catch (e) {
            // 备用方案：如果浏览器不支持该属性
            this.ctx = this.canvas.getContext('2d');
        }
    }

    // 创建缩略图 - 保持100x100以保证显示质量
    async createThumbnail(img, maxWidth = 100, maxHeight = 100) {
        let { width, height } = img;

        if (width > height) {
            if (width > maxWidth) {
                height *= maxWidth / width;
                width = maxWidth;
            }
        } else {
            if (height > maxHeight) {
                width *= maxHeight / height;
                height = maxHeight;
            }
        }

        this.canvas.width = width;
        this.canvas.height = height;
        this.ctx.clearRect(0, 0, width, height);
        this.ctx.drawImage(img, 0, 0, width, height);
        return this.canvas.toDataURL('image/jpeg', 0.7);
    }

    // 从Blob创建Image对象
    async createImageFromBlob(blob) {
        return new Promise((resolve, reject) => {
            const img = new Image();
            img.onload = () => resolve(img);
            img.onerror = () => reject(new Error('图片加载失败'));
            img.src = URL.createObjectURL(blob);
        });
    }

    // 算法1: 颜色直方图 - 保持原始64x64精度
    async calculateColorHistogram(img) {
        // 保持64x64尺寸以保证准确性
        this.canvas.width = 64;
        this.canvas.height = 64;
        this.ctx.clearRect(0, 0, 64, 64);
        this.ctx.drawImage(img, 0, 0, 64, 64);

        const imageData = this.ctx.getImageData(0, 0, 64, 64).data;

        // 64-bin 直方图 (4x4x4) - 保持原始精度
        const histogram = new Array(64).fill(0);
        const totalPixels = imageData.length / 4;

        for (let i = 0; i < imageData.length; i += 4) {
            const r = Math.floor(imageData[i] / 64);
            const g = Math.floor(imageData[i + 1] / 64);
            const b = Math.floor(imageData[i + 2] / 64);
            const index = r * 16 + g * 4 + b;
            histogram[index]++;
        }

        // 归一化
        for (let i = 0; i < histogram.length; i++) {
            histogram[i] /= totalPixels;
        }

        return histogram;
    }

    // 颜色直方图相似度 (巴氏系数)
    compareColorHistograms(hist1, hist2) {
        let similarity = 0;
        for (let i = 0; i < hist1.length; i++) {
            similarity += Math.sqrt(hist1[i] * hist2[i]);
        }
        return Math.min(1, Math.max(0, similarity));
    }

    // 算法2: 感知哈希 (pHash) - 保持原始32x32精度
    async calculatePerceptualHash(img) {
        // 保持32x32尺寸以保证准确性
        this.canvas.width = 32;
        this.canvas.height = 32;
        this.ctx.clearRect(0, 0, 32, 32);
        this.ctx.drawImage(img, 0, 0, 32, 32);
        const imageData = this.ctx.getImageData(0, 0, 32, 32);
        const grayPixels = this.getGrayPixels(imageData);

        // 计算DCT
        const dctData = this.simpleDCT(grayPixels, 32);

        // 取左上角8x8区域 - 保持原始精度
        const dctLowFreq = [];
        for (let y = 0; y < 8; y++) {
            for (let x = 0; x < 8; x++) {
                dctLowFreq.push(dctData[y * 32 + x]);
            }
        }

        // 计算中值并生成64位哈希
        const median = this.calculateMedian(dctLowFreq);
        let hash = 0n;

        for (let i = 0; i < dctLowFreq.length; i++) {
            if (dctLowFreq[i] > median) {
                hash |= 1n << BigInt(i);
            }
        }

        return hash;
    }

    // 获取灰度像素
    getGrayPixels(imageData) {
        const data = imageData.data;
        const grayPixels = new Array(32 * 32);

        for (let i = 0, j = 0; i < data.length; i += 4, j++) {
            grayPixels[j] = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
        }

        return grayPixels;
    }

    // 简化DCT变换
    simpleDCT(pixels, size) {
        const dct = new Array(size * size);

        for (let u = 0; u < size; u++) {
            for (let v = 0; v < size; v++) {
                let sum = 0;

                for (let x = 0; x < size; x++) {
                    for (let y = 0; y < size; y++) {
                        const pixel = pixels[y * size + x];
                        const cos1 = Math.cos((2 * x + 1) * u * Math.PI / (2 * size));
                        const cos2 = Math.cos((2 * y + 1) * v * Math.PI / (2 * size));
                        sum += pixel * cos1 * cos2;
                    }
                }

                const cu = u === 0 ? 1 / Math.sqrt(2) : 1;
                const cv = v === 0 ? 1 / Math.sqrt(2) : 1;
                dct[u * size + v] = 0.25 * cu * cv * sum;
            }
        }

        return dct;
    }

    // 计算中值
    calculateMedian(arr) {
        const sorted = [...arr].sort((a, b) => a - b);
        const mid = Math.floor(sorted.length / 2);
        return sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
    }

    // 计算汉明距离
    hammingDistance(hash1, hash2) {
        const xor = hash1 ^ hash2;
        let distance = 0;

        let temp = xor;
        while (temp > 0) {
            distance += Number(temp & 1n);
            temp >>= 1n;
        }

        return distance;
    }

    // pHash相似度 (基于汉明距离)
    comparePerceptualHashes(hash1, hash2) {
        const maxDistance = 64; // 8x8 = 64位
        const distance = this.hammingDistance(hash1, hash2);
        return Math.max(0, 1 - distance / maxDistance);
    }

    // 算法3: 颜色哈希 (快速算法) - 保持原始8x8精度
    async calculateColorHash(img) {
        // 保持8x8尺寸以保证准确性
        this.canvas.width = 8;
        this.canvas.height = 8;
        this.ctx.clearRect(0, 0, 8, 8);
        this.ctx.drawImage(img, 0, 0, 8, 8);
        const imageData = this.ctx.getImageData(0, 0, 8, 8);

        // 计算平均颜色
        let totalR = 0, totalG = 0, totalB = 0;
        const data = imageData.data;

        for (let i = 0; i < data.length; i += 4) {
            totalR += data[i];
            totalG += data[i + 1];
            totalB += data[i + 2];
        }

        const pixelCount = data.length / 4;
        const avgR = totalR / pixelCount;
        const avgG = totalG / pixelCount;
        const avgB = totalB / pixelCount;

        // 生成64位哈希
        let hash = 0n;
        for (let i = 0; i < data.length; i += 4) {
            const bitPos = i / 4;
            const isBrighter = (data[i] + data[i + 1] + data[i + 2]) > (avgR + avgG + avgB);
            if (isBrighter) {
                hash |= 1n << BigInt(bitPos);
            }
        }

        return hash;
    }

    // 颜色哈希相似度
    compareColorHashes(hash1, hash2) {
        const maxDistance = 64;
        const distance = this.hammingDistance(hash1, hash2);
        return Math.max(0, 1 - distance / maxDistance);
    }

    // 组合算法 (加权平均)
    compareCombined(features1, features2) {
        const weightHistogram = 0.4;
        const weightPerceptual = 0.4;
        const weightColorHash = 0.2;

        const histSimilarity = this.compareColorHistograms(
            features1.colorHistogram,
            features2.colorHistogram
        );

        const pHashSimilarity = this.comparePerceptualHashes(
            features1.perceptualHash,
            features2.perceptualHash
        );

        const colorHashSimilarity = this.compareColorHashes(
            features1.colorHash,
            features2.colorHash
        );

        return (
            histSimilarity * weightHistogram +
            pHashSimilarity * weightPerceptual +
            colorHashSimilarity * weightColorHash
        );
    }
}